package com.andy.blog.admin.service.impl;

import com.andy.blog.admin.dto.FileInfoDTO;
import com.andy.blog.admin.service.ConfigBusService;
import com.andy.blog.admin.service.FileBusService;
import com.andy.blog.common.constant.BaseConstants;
import com.andy.blog.common.constant.ConfigCenterConstants;
import com.andy.blog.common.enums.FileReNameEnum;
import com.andy.blog.common.exception.BlogServiceException;
import com.andy.blog.common.utils.DateUtils;
import com.andy.blog.common.utils.file.FileUtils;
import com.andy.blog.dal.vo.FileInfoVO;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * Created by andy on 2023/6/27 15:32
 */
@Service
public class FileBusServiceImpl implements FileBusService {

    private static final Logger logger = LoggerFactory.getLogger(FileBusServiceImpl.class);

    @Resource
    private ConfigBusService configBusService;

    @Override
    public FileInfoDTO uploadFile(MultipartFile file, FileInfoVO fileInfoVO) {

        if (Objects.isNull(file)) {
            throw new BlogServiceException("入参不能为空");
        }

        String fileName = file.getOriginalFilename();

        if (FileReNameEnum.FILE_RENAME_Y.getCode().equals(fileInfoVO.getIsReName())) {
            fileName = FileUtils.getRandomImgName(fileName);
        }

        String filePath = (StringUtils.isNotBlank(fileInfoVO.getFilePath()) ?
                fileInfoVO.getFilePath() + BaseConstants.SLASH : StringUtils.EMPTY) +
                DateUtils.formatDate(new Date(), DateUtils.YYYYMMDD) + BaseConstants.SLASH + fileName;

        String accessKey = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_ACCESS_KEY);
        String secretKey = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_SECRET_KEY);
        String bucketName = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_BUCKET_NAME);
        String url = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_URL);

        Configuration cfg = new Configuration(Region.autoRegion());
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucketName);

        try {
            Response response = uploadManager.put(file.getInputStream(), filePath, upToken, null, null);
            if (!response.isOK()) {
                throw new BlogServiceException("上传图片失败");
            }

            // 解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            logger.info("七牛图片上传key: {},七牛图片上传hash: {}", putRet.key, putRet.hash);

            return FileInfoDTO.builder()
                    .fileUrl(url + BaseConstants.SLASH + putRet.key)
                    .fileName(fileName)
                    .fileType(FileUtils.getFileType(fileName))
                    .build();
        } catch (QiniuException e) {
            logger.error("上传七牛云失败");
            throw new BlogServiceException("上传七牛云失败");
        } catch (IOException e) {
            logger.error("获取文件流信息失败");
            throw new BlogServiceException("获取文件流信息失败");
        }

    }

    @Override
    public void deleteFile(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            throw new BlogServiceException("文件路径不能为空");
        }

        String accessKey = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_ACCESS_KEY);
        String secretKey = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_SECRET_KEY);
        String bucketName = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_BUCKET_NAME);

        Configuration cfg = new Configuration(Region.autoRegion());
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);

        // 校验文件
        FileInfo fileInfo = null;
        try {
            fileInfo = bucketManager.stat(bucketName, filePath);
        } catch (QiniuException e) {
            e.printStackTrace();
        }

        if (Objects.isNull(fileInfo)) {
            return;
        }

        // 删除
        try {
            bucketManager.delete(bucketName, filePath);
        } catch (QiniuException e) {
            throw new BlogServiceException(String.valueOf(e.code()), e.response.toString());
        }
    }

    @Override
    public List<FileInfoDTO> listFiles() {

        String accessKey = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_ACCESS_KEY);
        String secretKey = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_SECRET_KEY);
        String bucketName = configBusService.selectConfigByKey(ConfigCenterConstants.OSS_QI_NIU_BUCKET_NAME);

        Configuration cfg = new Configuration(Region.autoRegion());
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);

        List<FileInfoDTO> fileInfoDTOList = new ArrayList<>();
        //文件名前缀
        String prefix = "";
        //每次迭代的长度限制，最大1000，推荐值 1000
        int limit = 1000;
        //指定目录分隔符，列出所有公共前缀（模拟列出目录效果）。缺省值为空字符串
        String delimiter = "";
        //列举空间文件列表
        BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucketName, prefix, limit, delimiter);
        while (fileListIterator.hasNext()) {
            //处理获取的file list结果
            FileInfo[] items = fileListIterator.next();
            for (FileInfo item : items) {
                FileInfoDTO fileInfoDTO = new FileInfoDTO();
                fileInfoDTO.setFileName(item.key);
                fileInfoDTO.setFileSize(item.fsize / 1024 + "KB");
                fileInfoDTO.setFileType(item.mimeType);
                fileInfoDTO.setCreateTime(DateUtils.getDateByTimestamp(item.putTime));
                fileInfoDTOList.add(fileInfoDTO);
            }
        }
        return fileInfoDTOList;
    }
}
